package com.example.utils;

import com.alibaba.fastjson.JSON;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 封装 FastDFS 上传工具类
 */
public class FastDFSClientUtil {
    private static final Logger logger = LoggerFactory.getLogger(FastDFSClientUtil.class);

    /**
     * 加载配置文件
     */
    static {
        try {
            String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            logger.error("FastDFS 初始化异常!", e);
        }
    }

    /**
     * 上传
     */
    public static String[] upload(String name, byte[] content, String ext) {
        return upload(name, content, ext);
    }

    /**
     * 上传（带元数据）
     *
     * @param name    文件名
     * @param content 文件流
     * @param ext     扩展名
     * @param metaMap 元数据
     * @return
     */
    public static String[] upload(String name, byte[] content, String ext, Map<String, String> metaMap) {
        String[] uploadResults = null;
        StorageClient storageClient = null;
        NameValuePair[] nameValuePairs = null;
        try {
            storageClient = getTrackerClient();

            if (!CollectionUtils.isEmpty(metaMap)) {
                Map<String, String> map = metaMap;
                List<NameValuePair> metaList = new ArrayList<>();
                map.forEach((k, v) -> metaList.add(new NameValuePair(k, v)));
                nameValuePairs = metaList.toArray(new NameValuePair[]{});
            }

            uploadResults = storageClient.upload_file(content, ext, nameValuePairs);
        } catch (IOException e) {
            logger.error("IO异常:" + name, e);
        } catch (Exception e) {
            logger.error("上传异常:" + name, e);
        }

        if (uploadResults == null && storageClient != null) {
            logger.error("上传失败，异常代码:" + storageClient.getErrorCode());
        }
        logger.info("上传成功：" + JSON.toJSON(uploadResults));
        return uploadResults;
    }

    /**
     * 获取文件信息
     *
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static FileInfo getFile(String groupName, String remoteFileName) {
        try {
            StorageClient storageClient = getTrackerClient();
            return storageClient.get_file_info(groupName, remoteFileName);
        } catch (Exception e) {
            logger.error("Fast DFS 获取文件信息异常", e);
        }
        return null;
    }

    /**
     * 下载
     *
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static InputStream downFile(String groupName, String remoteFileName) {
        try {
            StorageClient storageClient = getTrackerClient();
            byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
            InputStream ins = new ByteArrayInputStream(fileByte);
            return ins;
        } catch (Exception e) {
            logger.error("Fast DFS 获取文件异常", e);
        }
        return null;
    }

    /**
     * 删除
     */
    public static void deleteFile(String groupName, String remoteFileName) throws Exception {
        StorageClient storageClient = getTrackerClient();
        int i = storageClient.delete_file(groupName, remoteFileName);
        logger.info("删除文件成功：" + i);
    }

    public static StorageServer[] getStoreStorages(String groupName) throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerClient.getStoreStorages(trackerServer, groupName);
    }

    public static ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
    }

    private static StorageClient getTrackerClient() throws IOException {
        TrackerServer trackerServer = getTrackerServer();
        StorageClient storageClient = new StorageClient(trackerServer, null);
        return storageClient;
    }

    private static TrackerServer getTrackerServer() throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerServer;
    }

    /**
     * 获取访问服务器的token，拼接到地址后面
     *
     * @param fileId 文件路径 group1/M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
     * @param httpSecretKey 秘钥
     * @return 返回token，如： token=078d370098b03e9020b82c829c205e1f&ts=1508141521
     */
    public static String getToken(String fileId, String httpSecretKey){
        // unix seconds
        int ts = (int) Instant.now().getEpochSecond();
        // token
        String token = "null";
        try {
            token = ProtoCommon.getToken(fileId, ts, httpSecretKey);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

        StringBuilder sb = new StringBuilder();
        sb.append("token=").append(token);
        sb.append("&ts=").append(ts);

        return sb.toString();
    }
}
